#include "inferenceengine.h"
#include <QDebug>
#include <algorithm>

/**
 * @brief 构造函数
 * @param ruleManager 规则管理器指针
 * @param factManager 事实管理器指针
 * @param parent 父对象，默认为nullptr
 */
InferenceEngine::InferenceEngine(RuleManager *ruleManager, FactManager *factManager, QObject *parent)
    : QObject(parent),
      m_ruleManager(ruleManager),
      m_factManager(factManager)
{
    // 连接信号和槽
    if (m_factManager) {
        connect(m_factManager, &FactManager::factAdded, this, &InferenceEngine::onFactAdded);
        
        // 添加初始事实到事实管理器
        m_factManager->addFact("初始化系统");
    }
}

/**
 * @brief 设置规则管理器
 * @param ruleManager 规则管理器指针
 */
void InferenceEngine::setRuleManager(RuleManager *ruleManager)
{
    m_ruleManager = ruleManager;
}

/**
 * @brief 设置事实管理器
 * @param factManager 事实管理器指针
 */
void InferenceEngine::setFactManager(FactManager *factManager)
{
    // 断开原有事实管理器的连接
    if (m_factManager) {
        disconnect(m_factManager, &FactManager::factAdded, this, &InferenceEngine::onFactAdded);
    }
    
    m_factManager = factManager;
    
    // 连接新事实管理器
    if (m_factManager) {
        connect(m_factManager, &FactManager::factAdded, this, &InferenceEngine::onFactAdded);
    }
}

/**
 * @brief 执行前向推理
 * @return 推导出的结论
 * 
 * 前向推理是一种从已知事实出发，应用规则推导出新事实的方法，
 * 直到无法推导出更多事实为止。推理过程包括规则匹配、冲突消解等步骤。
 */
QString InferenceEngine::forwardChaining()
{
    // 检查规则管理器和事实管理器是否已设置
    if (!m_ruleManager || !m_factManager) {
        qDebug() << "错误: 规则管理器或事实管理器未设置";
        return "错误: 系统组件未正确初始化";
    }
    
    bool hasNewFact = true; // 是否有新事实被推导出
    QString conclusion; // 最终结论
    int iteration = 0; // 推理轮次计数
    
    // 清空推理步骤记录
    m_inferenceSteps.clear();
    emit inferenceStarted();
    
    // 循环推理，直到无法推导出新事实
    while (hasNewFact) {
        iteration++;
        hasNewFact = false;
        
        // 通知当前推理状态
        QString stepDesc = QString("【推理轮次 %1】事实数: %2").arg(iteration).arg(m_factManager->getFactCount());
        emit inferenceStep(stepDesc);
        m_inferenceSteps.append(stepDesc);
        
        // 查找所有可用规则
        QList<Rule*> applicableRules = findApplicableRules();
        
        if (!applicableRules.isEmpty()) {
            // 通知匹配的规则数量
            QString matchInfo = QString("【规则匹配】找到 %1 条规则").arg(applicableRules.size());
            emit inferenceStep(matchInfo);
            m_inferenceSteps.append(matchInfo);
            
            // 冲突消解（选优先级最高的）
            Rule* selectedRule = resolveConflict(applicableRules);
            
            // 发出冲突消解步骤信号
            QStringList ruleNames;
            for (Rule* rule : applicableRules) {
                ruleNames.append(rule->getName());
            }
            QString selectedRuleName = selectedRule ? selectedRule->getName() : "无";
            emit conflictResolutionStep(ruleNames, selectedRuleName);
            
            // 执行规则（添加结论到事实库）
            if (selectedRule && m_factManager->addFact(selectedRule->getConclusion())) {
                hasNewFact = true;
                
                QString applyInfo = QString("【应用规则】%1 → %2")
                    .arg(selectedRule->getName())
                    .arg(selectedRule->getConclusion());
                emit inferenceStep(applyInfo);
                m_inferenceSteps.append(applyInfo);
                
                // 检查是否是结论
                if (selectedRule->getConclusion().startsWith("结论:")) {
                    conclusion = selectedRule->getConclusion();
                    QString conclusionInfo = QString("【最终结论】%1").arg(conclusion);
                    emit inferenceStep(conclusionInfo);
                    m_inferenceSteps.append(conclusionInfo);
                    break;
                }
            }
            
            // 清理动态分配的Rule对象
            qDeleteAll(applicableRules);
        } else {
            QString noMatchInfo = "【无匹配规则】";
            emit inferenceStep(noMatchInfo);
            m_inferenceSteps.append(noMatchInfo);
        }
    }
    
    // 发送推理完成信号
    if (conclusion.isEmpty()) {
        emit inferenceCompleted("无法得出确定的结论");
    } else {
        emit inferenceCompleted(conclusion);
    }
    
    return conclusion;
}

/**
 * @brief 查找所有可应用的规则
 * @return 可应用的规则列表
 * 
 * 遍历所有规则，检查每个规则的所有条件是否都在事实库中，
 * 如果所有条件都满足，则将该规则添加到可应用规则列表中。
 */
QList<Rule*> InferenceEngine::findApplicableRules() const
{
    // 检查规则管理器和事实管理器是否已设置
    if (!m_ruleManager || !m_factManager) {
        return QList<Rule*>();
    }
    
    QList<Rule> allRules = m_ruleManager->getAllRules();
    QList<Rule*> applicable;
    
    // 遍历所有规则
    foreach (Rule rule, allRules) {
        bool allPremisesSatisfied = true;
        
        // 检查规则的所有条件是否都在事实库中
        foreach (QString premise, rule.getConditions()) {
            if (!m_factManager->hasFact(premise)) {
                allPremisesSatisfied = false;
                break;
            }
        }
        
        // 如果所有条件都满足且结论不在事实库中，则将该规则添加到可应用规则列表中
        if (allPremisesSatisfied && !m_factManager->hasFact(rule.getConclusion())) {
            // 创建Rule对象的副本并添加到适用规则列表中
            Rule* ruleCopy = new Rule(rule);
            applicable.append(ruleCopy);
        }
    }
    
    return applicable;
}

/**
 * @brief 冲突消解
 * @param rules 候选规则列表
 * @return 选中的规则
 * 
 * 当多个规则同时可应用时，需要通过冲突消解策略选择一个规则。
 * 冲突消解策略：
 * 1. 优先选择结论是"结论:"开头的规则（最终结论）
 * 2. 如果没有最终结论规则，则选择条件数最多的规则（更具体）
 * 3. 如果条件数相同，则选择第一条规则
 */
Rule* InferenceEngine::resolveConflict(const QList<Rule*>& rules) const
{
    // 如果规则列表为空，返回nullptr
    if (rules.isEmpty()) {
        return nullptr;
    }
    
    // 首先查找结论是"结论:"开头的规则
    for (Rule* rule : rules) {
        if (rule->getConclusion().startsWith("结论:")) {
            return rule;
        }
    }
    
    // 如果没有最终结论规则，则选择条件数最多的规则
    Rule* bestRule = rules.first();
    int maxConditions = bestRule->getConditions().size();
    
    for (Rule* rule : rules) {
        int conditionCount = rule->getConditions().size();
        if (conditionCount > maxConditions) {
            maxConditions = conditionCount;
            bestRule = rule;
        }
    }
    
    return bestRule;
}

/**
 * @brief 获取推理步骤记录
 * @return 推理步骤列表
 */
QStringList InferenceEngine::getInferenceSteps() const
{
    return m_inferenceSteps;
}

/**
 * @brief 响应事实添加事件的槽函数
 * @param fact 新添加的事实
 * 
 * 当有新事实添加时，发出信号通知UI更新
 */
void InferenceEngine::onFactAdded(const QString &fact)
{
    // 当有新事实添加时，发出信号通知UI更新
    emit factAdded(fact);
}